package com.grace.cms.general.taglib;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import com.grace.common.utils.DateUtils;
import com.grace.redis.utils.RedisCache;
import com.alibaba.fastjson2.JSON;
import com.grace.cms.common.enums.ArticleSortEnums;
import com.grace.cms.common.enums.ArticleTypeEnums;
import com.grace.cms.common.enums.OrderEnums;
import com.grace.cms.common.model.TimeNum;
import com.grace.cms.common.model.support.PageData;
import com.grace.cms.general.cache.GeneralArticleCacheService;
import com.grace.cms.query.model.vo.WebArticleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 文章标签 涉及文章表的操作
 */
@Service("articleTag")
public class ArticleTag {
    @Autowired
    private GeneralArticleCacheService articleService;
    @Autowired
    private RedisCache redisCache;

    /**
     * 获取文章数量
     * 
     * @param themeName
     * @param articleTypeEnums
     * @return
     */
    public int selectArticleNumByType(String themeName, ArticleTypeEnums articleTypeEnums) {
        return articleService.selectArticleNum(themeName, articleTypeEnums);
    }

    /**
     * 获取文章数量
     * 
     * @param themeName
     * @return
     */
    public int selectArticleNum(String themeName) {
        return articleService.selectArticleNum(themeName);
    }

    /**
     * 依据年月获取文章数量
     * 
     * @param themeName
     * @param pageNum
     * @param pageSize
     * @return
     */
    public List<TimeNum> listArticleTimeNum(String themeName, int pageNum, int pageSize) {
        return articleService.listArticleTimeNum(themeName, pageNum, pageSize);
    }

    /**
     * 获取文章Html
     * 
     * @param articleId
     * @return
     */
    public WebArticleVo selectWebArticleHtmlById(Long articleId, String themeName) {
        return articleService.selectWebArticleById(articleId, themeName, false, true);
    }

    /**
     * 获取文章MarkDown
     * 
     * @param articleId
     * @return
     */
    public WebArticleVo selectWebArticleMdById(Long articleId, String themeName) {
    return articleService.selectWebArticleById(articleId, themeName, true, false);
    }
    
 

    /**
     * 获取文章Html
     * 
     * @param articleUrl
     * @return
     */
    public WebArticleVo selectWebArticleHtmlByUrl(String articleUrl, String themeName) {
        return articleService.selectWebArticleByUrl(articleUrl, themeName, false, true);
    }

    /**
     * 获取文章MarkDown
     * 
     * @param articleUrl
     * @return
     */
    public WebArticleVo selectWebArticleMdByUrl(String articleUrl, String themeName) {
        return articleService.selectWebArticleByUrl(articleUrl, themeName, true, false);
    }

    /**
     * 
     * @param themeName
     * @param categoryId
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageData<WebArticleVo> listWebArticleByCategoryId(String themeName, long categoryId, int pageNum,
            int pageSize) {
        return this.pageWebArticleBy(themeName, null, categoryId, null, pageNum, pageSize, getOrder(OrderEnums.DESC));
    }

    /**
     * 
     * @param themeName
     * @param articleType
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageData<WebArticleVo> listWebArticleByCategoryId(String themeName, long categoryId, int pageNum,
            int pageSize,
            OrderEnums order) {
        return this.pageWebArticleBy(themeName, null, categoryId, null, pageNum, pageSize, getOrder(order));
    }

    /**
     * 依据类型
     * 
     * @param themeName
     * @param articleType
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageData<WebArticleVo> listWebArticleByType(String themeName, int articleType, int pageNum, int pageSize) {
        return this.pageWebArticleBy(themeName, articleType, null, null, pageNum, pageSize,
                getOrder(OrderEnums.DESC));
    }

    /**
     * 
     * @param articleType
     * @param pageNum
     * @param pageSize
     * @param order
     * @return
     */
    public PageData<WebArticleVo> listWebArticleByType(String themeName, int articleType, int pageNum, int pageSize,
            OrderEnums order) {
        return this.pageWebArticleBy(themeName, articleType, null, null, pageNum, pageSize, getOrder(order));
    }

    /**
     * 文章列表
     * 
     * @param themeName
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageData<WebArticleVo> pageArticles(String themeName, int pageNum, int pageSize) {
        return this.pageWebArticleBy(themeName, null, null, null, pageNum, pageSize,
                getOrder(OrderEnums.DESC));
    }

    /**
     * 文章列表
     * 
     * @param themeName
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageData<WebArticleVo> pageArticles(String themeName, int pageNum, int pageSize, OrderEnums order) {
        return this.pageWebArticleBy(themeName, null, null, null, pageNum, pageSize,
                getOrder(order));
    }

    private String getOrder(OrderEnums order) {
        return "article_top desc,create_time " + order.name();
    }

    public PageData<Long> getArticleIds(String themeName, Integer articleType, Long categoryId, String crTime,
            int pageNum,
            int pageSize, String order) {
        return articleService.selectArticleIds(themeName, articleType, categoryId, crTime, pageNum,
                pageSize, order);
    }

    public PageData<WebArticleVo> groupOrderByTime(String themeName, String crTime, int pageNum, int pageSize) {
        PageData<WebArticleVo> pageData = this.pageWebArticleBy(themeName, null, null, crTime,
                pageNum, pageSize, ArticleSortEnums.ARTICLE_TOP.getOrder(OrderEnums.DESC));
        pageData.setTimeLineData(pageData.getRows().stream()
                .collect(Collectors.groupingBy(webArticle -> DateUtils.neData(webArticle.getCreateTime()))));
        return pageData;
    }

    public PageData<WebArticleVo> pageWebArticleBy(String themeName, Integer articleType, Long categoryId,
            String crTime, int pageNum, int pageSize,
            String order) {
        PageData<Long> articleIdPageData = this.getArticleIds(themeName, articleType, categoryId, crTime, pageNum,
                pageSize,
                order);
        ArrayList<Object> articleIdObjects = new ArrayList<>(articleIdPageData.getRows().stream()
                .map(Object::toString)
                .collect(Collectors.toList()));
        List<Object> rawList = redisCache.getMultiCacheMapValue(
                 GeneralArticleCacheService.baseKeyPrefix,
                articleIdObjects);
        List<WebArticleVo> listArticle = rawList.stream()
                .map(obj -> JSON.parseObject(JSON.toJSONString(obj), WebArticleVo.class))
                .collect(Collectors.toList());

        if (listArticle.stream().anyMatch(article -> article == null)) {
            return new PageData<>(articleIdPageData.getTotal(), articleIdPageData.getCode(),
                    articleIdPageData.getPages(), articleIdPageData.getPageNum(), articleIdPageData.getPageSize(),
                    changWebArticleVos(listArticle, articleIdObjects, themeName, articleType, categoryId, crTime,
                            pageNum,
                            pageSize, order));
        } else {
            return new PageData<>(articleIdPageData.getTotal(), articleIdPageData.getCode(),
                    articleIdPageData.getPages(), articleIdPageData.getPageNum(), articleIdPageData.getPageSize(),
                    listArticle);
        }

    }

    private List<WebArticleVo> changWebArticleVos(List<WebArticleVo> listArticle, List<Object> articleIdObjects,
            String themeName,
            Integer articleType, Long categoryId, String crTime, int pageNum, int pageSize,
            String order) {
        // 创建一个新的列表用于保存非空的 WebArticleVo 项
        List<WebArticleVo> nonNullArticles = new ArrayList<>();
        // 迭代 listArticle
        for (int i = 0; i < listArticle.size(); i++) {
            WebArticleVo article = listArticle.get(i);
            if (article != null) {
                // 如果当前项不为 null，则添加到新列表中
                nonNullArticles.add(article);
            } else {
                Long notArticleId = Long.valueOf(articleIdObjects.get(i).toString());
                article = articleService.selectWebArticleById(notArticleId, themeName, true, true);
                if (article != null) {
                    nonNullArticles.add(article);
                } else {
                    // 清除缓存
                    articleService.articleEvict(themeName, articleType, categoryId, crTime, pageNum, pageSize, order);
                }
            }
        }
        return nonNullArticles;
    }

}
